#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
__author__ = 'Justin'
__mtime__ = '2020-11-12'

"""

import os
import cv2
import numpy as np
import pandas as pd


def get_project_root():
    path = os.getcwd()
    # 约定 项目的代码在src文件夹，其它的目录与它平级
    pos = path.find("src")
    if pos > 0:
        return path[:pos - 1]
    else:
        return path


def get_skin_yuv(img):
    lower = np.array([80, 133, 77], dtype=np.int32)
    upper = np.array([255, 173, 127], dtype=np.int32)

    convert_img = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
    skinMask = cv2.inRange(convert_img, lower, upper)

    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11, 11))
    skinMask = cv2.erode(skinMask, kernel, iterations=2)
    skinMask = cv2.dilate(skinMask, kernel, iterations=2)

    skinMask = cv2.GaussianBlur(skinMask, (3, 3), 0)

    return np.array(skinMask, dtype=np.bool)


def latest_checkpoint(search_dir, is_acc=True):
    '''
    在指定目录下，获取最新的模型存盘文件
    :param search_dir: 指定的目录路径
    :param is_acc: 文件名称中的数据部分是准确率，还是loss值
    :return:
    '''
    filename = []
    epoch = []
    train_accuracy = []
    test_accuracy = []

    for ckpt_name in os.listdir(search_dir):
        file_name = os.path.splitext(ckpt_name)[0]
        value = file_name.split("-")
        if len(value) >= 4:
            filename.append(ckpt_name)
            epoch.append(int(value[1]))
            train_accuracy.append(float(value[2]))
            test_accuracy.append(float(value[3]))

    if len(filename) == 0:
        return None

    if is_acc:
        data = {'filename': filename, 'epoch': epoch, 'train_acc': train_accuracy, 'test_acc': test_accuracy}
        df = pd.DataFrame(data, columns=['filename', 'epoch', 'train_acc', 'test_acc'])
        result = df.sort_values(['test_acc', 'train_acc', 'epoch'], ascending=[False, False, False])
    else:
        data = {'filename': filename, 'epoch': epoch, 'train_loss': train_accuracy, 'test_loss': test_accuracy}
        df = pd.DataFrame(data, columns=['filename', 'epoch', 'train_loss', 'test_loss'])
        result = df.sort_values(['test_loss', 'train_loss', 'epoch'], ascending=[True, True, False])
    path = "{}/{}".format(search_dir, result.iloc[0, 0])
    return path


def softmax(x):
    """ softmax function """

    # assert(len(x.shape) > 1, "dimension must be larger than 1")
    # print(np.max(x, axis = 1, keepdims = True)) # axis = 1, 行

    x -= np.max(x, axis=1, keepdims=True)  # 为了稳定地计算softmax概率， 一般会减掉最大的那个元素

    # print("减去行最大值 ：\n", x)

    x = np.exp(x) / np.sum(np.exp(x), axis=1, keepdims=True)

    return x


def segment(pred, prob):
    '''
    对预测的动作标记进行分段
    :param pred: 动作标记序列
    :param prob: 对应的概率
    :return: 分段区间信息
    '''
    start = 0
    pre_label = pred[start]
    nx_label = None
    seg = []
    for i in range(1, len(pred)):
        nx_label = pred[i]
        if pre_label != nx_label:
            seg_prob = prob[start:i, pre_label]
            prob_count = i - start
            prob_std = np.std(seg_prob)
            prob_mean = np.mean(seg_prob)
            # 开始帧数，结果帧数，标注，长度，概率均值，标准差
            seg.append((start, i - 1, pre_label, prob_count, prob_mean, prob_std))
            start = i
            pre_label = nx_label

    end = len(pred)
    seg_prob = prob[start:end, nx_label]
    prob_std = np.std(seg_prob)
    prob_mean = np.mean(seg_prob)
    seg.append((start, end, nx_label, end - start, prob_mean, prob_std))

    return seg
